package com.lxujia.ruankao.util;

import android.content.Context;
import android.content.res.AssetManager;
import android.text.TextUtils;
import android.util.Log;

import com.lxujia.ruankao.model.CategoryItem;
import com.lxujia.ruankao.model.CategoryType;
import com.lxujia.ruankao.model.DbInitModel;
import com.lxujia.ruankao.model.QuestionItem;

import org.litepal.LitePal;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DatabaseInitUtil {
    private final static String TAG = "DatabaseInitUtil";
    private Context mContext;
    private AssetManager mAssetManager;

    public DatabaseInitUtil(Context context) {
        mContext = context;
        mAssetManager = mContext.getAssets();
    }


    public void initDbData() {
        LogUtil.d(TAG, "initDbData");

        ExecutorsUtil.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                clearDb();

                initCategoryDb();

                initQuestion();

                initDbSuccess();
            }
        });
    }

    // 初始化DB前，先清空所有数据
    private void clearDb() {
        LogUtil.d(TAG, "clearDb");

        LitePal.deleteAll(CategoryType.class);
        LitePal.deleteAll(CategoryItem.class);
        LitePal.deleteAll(QuestionItem.class);
        LitePal.deleteAll(DbInitModel.class);
    }

    // 数据库初始化完成，更新到表。
    // 防止为初始化完成，应用被kill，下次启动数据库不完整问题
    private void initDbSuccess() {
        LogUtil.d(TAG, "initDbSuccess");
        DbInitModel dbInitModel = new DbInitModel(1);
        dbInitModel.save();
    }

    private void initQuestion() {
        LogUtil.d(TAG, "initQuestion");
        // 查询 CategoryItem DB
        List<CategoryItem> categoryItems = LitePal.findAll(CategoryItem.class);
        for(CategoryItem item : categoryItems) {
            LogUtil.d(TAG, "initQuestion item = " + item);
            String assetsFile = item.getAssetsFile();
            if (TextUtils.isEmpty(assetsFile)) {
                continue;
            }
            LogUtil.d(TAG, "initQuestion assetsFile = " + assetsFile);

            List<QuestionItem> questionItems = getQuestionItems(assetsFile);
            if (questionItems == null || questionItems.size() == 0) {
                continue;
            }

            item.setQuestionItems(questionItems);
            item.save();
        }
    }

    private String[] getQuestionImageFiles(String assetsFile) {
        String path = ConstantUtil.CATEGORY_IMAGE_DIR + assetsFile;
        LogUtil.d(TAG, "getQuestionImageFiles path = " + path);
        String[] imageFiles = null;
        try {
            imageFiles = mAssetManager.list(path);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return imageFiles;
    }

    private List<QuestionItem> getQuestionItems(String assetsFile) {
        LogUtil.d(TAG, "getQuestionItems assetsFile = " + assetsFile);
        BufferedReader reader = null;
        List<QuestionItem> list = new ArrayList<QuestionItem>();

        String[] imageFiles = getQuestionImageFiles(assetsFile);
        try {
            reader = new BufferedReader(new InputStreamReader(mAssetManager.open(assetsFile)));
            String tempString;
//            int line = 1;
            // 一次读入一行，直到读入null为文件结束
            int type = ConstantUtil.TYPE_TITLE; // 默认第一行为 题目
            String answerDesc = ConstantUtil.ANSWER_DESC_START + "\n";//问题详解
            String questionTitle = "";//问题题目
            String answerList = ""; //问题选项
            String rightAnswer = "";//正确答案
            String answerDescImage = ""; // 问题详解插图
            String questionTitleImage = "";  // 问题插图
            String answerListImage = ""; // 问题选项插图
            int no = -1; //问题序号
            while ((tempString = reader.readLine()) != null) {
                // 显示行号
//                System.out.println("line " + line + ": " + tempString);
//                line++;
                //LogUtil.d(TAG, "getQuestionItems tempString = " + tempString);
                if (TextUtils.isEmpty(tempString)) {
                    continue;
                }
                if (isAnswerDesc(tempString)) { // 解析内容开始行，之后内容都是解析，直到出现正确答案
                    type = ConstantUtil.TYPE_ANSWER_DESC;
                    continue; // 此行之后的才是解析，此行可舍弃
                }
                if (isRightAnswer(tempString)) { // 正确答案行，只有一行
                    type = ConstantUtil.TYPE_RIGHT_ANSWER;
                    answerDesc += tempString + "\n";
                    rightAnswer = tempString.replaceFirst(ConstantUtil.RIGHT_ANSWER_START, "").trim();
                    LogUtil.d(TAG, "no = " + no);
                    LogUtil.d(TAG, "questionTitle = " + questionTitle);
                    LogUtil.d(TAG, "questionDesc = " + answerDesc);
                    LogUtil.d(TAG, "rightAnswer = " + rightAnswer);
                    LogUtil.d(TAG, "answerList = " + answerList);

                    if (no <= 0 || TextUtils.isEmpty(questionTitle) || TextUtils.isEmpty(answerList) ||
                            TextUtils.isEmpty(rightAnswer)) {
                        LogUtil.d(TAG, "getQuestionItems empty");
                        continue;
                    }

                    answerDescImage = getQuestionImage(no, assetsFile, imageFiles,
                            ConstantUtil.IMAGE_TYPE_ANSWER_DESC);
                    questionTitleImage = getQuestionImage(no, assetsFile, imageFiles,
                            ConstantUtil.IMAGE_TYPE_TITLE);
                    answerListImage = getQuestionImage(no, assetsFile, imageFiles,
                            ConstantUtil.IMAGE_TYPE_ANSWER_LIST);

                    QuestionItem questionItem = new QuestionItem(no, questionTitle, answerDesc,
                            rightAnswer, answerList);
                    questionItem.setAnswerDescImage(answerDescImage);
                    questionItem.setAnswerListImage(answerListImage);
                    questionItem.setQuestionImage(questionTitleImage);
                    questionItem.save();
                    list.add(questionItem);
                    type = ConstantUtil.TYPE_TITLE;
                    questionTitle = "";
                    answerList = "";
                    answerDesc = ConstantUtil.ANSWER_DESC_START + "\n";
                    continue;
                }
                if (type == ConstantUtil.TYPE_ANSWER_DESC) {
                    answerDesc += tempString + "\n";
                    continue;
                }
                if (type == ConstantUtil.TYPE_TITLE) {
                    String noStr = getQuestionTitleNo(tempString);
                    if (!TextUtils.isEmpty(noStr)) {
                        no = Integer.parseInt(noStr);
                    }

                    String answer = getAnswerList(tempString);
                    if (!TextUtils.isEmpty(answer)) {
                        answerList += answer + ConstantUtil.STRING_LIST_SPLIT;
                        continue;
                    }
                    questionTitle += tempString + "\n";
                    continue;
                }
            }
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (Exception e1) {
                }
            }
        }

        return list;
    }

    private String getQuestionImage(int no, String assetsFile, String[] imageFiles, int imageType) {
        String path = ConstantUtil.CATEGORY_IMAGE_DIR + assetsFile + "/";
        LogUtil.d(TAG, "getQuestionImage path = " + path);
        String images = "";
        if (imageFiles == null || imageFiles.length == 0 || no <= 0) {
            return images;
        }
        for (String imageFile : imageFiles) {
            if (imageType == ConstantUtil.IMAGE_TYPE_TITLE &&
                    imageFile.startsWith(no + ConstantUtil.QUESTION_TITLE_IMAGE)) {
                images = path + imageFile + ConstantUtil.STRING_LIST_SPLIT;
            }
            if (imageType == ConstantUtil.IMAGE_TYPE_ANSWER_LIST &&
                    imageFile.startsWith(no + ConstantUtil.QUESTION_ANSWER_LIST_IMAGE)) {
                images = path + imageFile + ConstantUtil.STRING_LIST_SPLIT;
            }
            if (imageType == ConstantUtil.IMAGE_TYPE_ANSWER_DESC &&
                    imageFile.startsWith(no + ConstantUtil.QUESTION_ANSWER_DESC_IMAGE)) {
                images = path + imageFile + ConstantUtil.STRING_LIST_SPLIT;
            }
        }
        LogUtil.d(TAG, "getQuestionImage images = " + images + " ; no = " + no +
                " ; imageType = " + imageType);
        return images;
    }

    private boolean isRightAnswer(String lineStr) {
        if (lineStr.startsWith(ConstantUtil.RIGHT_ANSWER_START)) {
            return true;
        }
        return false;
    }

    private boolean isAnswerDesc(String lineStr) {
        if (lineStr.startsWith(ConstantUtil.ANSWER_DESC_START)) {
            return true;
        }
        return false;
    }

    private String getAnswerList(String tempString) {
        // 题目选项以 A/B/C/D 或者 a/b/c/d开头，且后面的字符为中文符号、
        Pattern pattern = Pattern.compile("^[a-dA-D](.*)");
        Matcher matcher = pattern.matcher(tempString);
        if (matcher.matches()) {
            LogUtil.d(TAG, "getAnswerList answerTitle = " + matcher.group(0));
            LogUtil.d(TAG, "getAnswerList answerText = " + matcher.group(1));
            String answerTitle = matcher.group(0);
            String answerText = matcher.group(1);
            if (TextUtils.isEmpty(answerTitle) || TextUtils.isEmpty(answerText)) {
                return null;
            }
            if (answerText.startsWith(ConstantUtil.QUESTION_SPLIT_COMMA)) {
                LogUtil.d(TAG, "answerText = " + answerText);
                return answerText.replaceFirst(ConstantUtil.QUESTION_SPLIT_COMMA, "");
            }
        }
        return null;
    }

    private String getQuestionTitleNo(String tempString) {
        // 题目以数字开头，且数字后面的字符为中文符号、
        Pattern pattern = Pattern.compile("^(\\d+)(.*)");
        Matcher matcher = pattern.matcher(tempString);
        if (matcher.matches()) {
            LogUtil.d(TAG, "title1 = " + matcher.group(1));
            LogUtil.d(TAG, "title2 = " + matcher.group(2));
            String no = matcher.group(1);
            String title = matcher.group(2);
            if (TextUtils.isEmpty(no) || TextUtils.isEmpty(title)) {
                return null;
            }
            if (title.startsWith(ConstantUtil.QUESTION_SPLIT_COMMA)) {
                LogUtil.d(TAG, "title = " + title);
                return no;
            }
        }
        return null;
    }

    private void initCategoryDb() {
        String[] files = null;

        Set<String> setKey = ConstantUtil.CATEGORY_TYPE_LIST.keySet();
        Iterator<String> iterator = setKey.iterator();
        while(iterator.hasNext()) {
            String type = iterator.next();;
            try {
                files = mAssetManager.list(type);
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (files == null || files.length == 0) {
                continue;
            }

            LogUtil.d(TAG, "initCategoryDb path = " + type);

            List<CategoryItem> categoryItems = initCategoryItem(type, files);

            CategoryType categoryType = new CategoryType(type,
                    ConstantUtil.CATEGORY_TYPE_LIST.get(type), categoryItems);
            LogUtil.d(TAG, "initCategoryDb " + categoryType);
            categoryType.save();
        }
    }

    private List<CategoryItem> initCategoryItem(String type, String[] files) {
        List<CategoryItem> items = new ArrayList<CategoryItem>();
        for(String period : files) {
            LogUtil.d(TAG, "initCategoryItem period = " + period);
            CategoryItem categoryItem = new CategoryItem();
            categoryItem.setPeriod(period);

            String[] periodYM = getPeroidYM(period);
            if (periodYM == null) {
                LogUtil.d(TAG, "initCategoryItem periodYM is null");
                continue;
            }
            if (ConstantUtil.PERIOD_LIST.containsKey(periodYM[1])) {
                categoryItem.setPeriodToShow(periodYM[0] +
                        ConstantUtil.PERIOD_LIST.get(periodYM[1]));
            }
            categoryItem.setAssetsFile(type + "/" + period);
            categoryItem.setExtInfo(ConstantUtil.EXT_INFO);
            categoryItem.save();

            LogUtil.d(TAG, "initCategoryItem categoryItem = " + categoryItem);
            items.add(categoryItem);
        }
        return items;
    }

    private String[] getPeroidYM(String peroid) {
        if (TextUtils.isEmpty(peroid)) {
            return null;
        }

        String[] periodYM = peroid.split("\\.");
        // period 格式为 2018.05,不符合此格式时返回 null
        if (periodYM == null || periodYM.length <= 0 || periodYM.length > 2) {
            return null;
        }
        return periodYM;
    }

    public void updateDbData() {
        ExecutorsUtil.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                updateCategoryDb();
            }
        });
    }

    private void updateQuestion(List<CategoryItem> categoryItems) {
        LogUtil.d(TAG, "updateQuestion");
        // 查询 CategoryItem DB
        for(CategoryItem item : categoryItems) {
            LogUtil.d(TAG, "updateQuestion item = " + item);
            String assetsFile = item.getAssetsFile();
            if (TextUtils.isEmpty(assetsFile)) {
                continue;
            }
            LogUtil.d(TAG, "updateQuestion assetsFile = " + assetsFile);

            List<QuestionItem> questionItems = getQuestionItems(assetsFile);
            if (questionItems == null || questionItems.size() == 0) {
                continue;
            }

            item.setQuestionItems(questionItems);
            item.save();
        }
    }

    private void updateCategoryDb() {
        String[] files = null;

        Set<String> setKey = ConstantUtil.CATEGORY_TYPE_LIST.keySet();
        Iterator<String> iterator = setKey.iterator();
        while(iterator.hasNext()) {
            String type = iterator.next();
            try {
                files = mAssetManager.list(type);
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (files == null || files.length == 0) {
                continue;
            }

            LogUtil.d(TAG, "updateCategoryDb path = " + type);

            List<CategoryItem> categoryItems = updateCategoryItem(type, files);

            if (categoryItems != null && categoryItems.size() > 0) {
                List<CategoryType> categoryTypeList = LitePal.where("categoryType == ?", type).
                        find(CategoryType.class);
                LogUtil.d(TAG, "updateCategoryItem categoryTypeList size : " + categoryTypeList.size());
                if (categoryTypeList == null || categoryTypeList.size() == 0) { // 数据库中不存在则保存到数据库
                    CategoryType categoryType = new CategoryType(type,
                            ConstantUtil.CATEGORY_TYPE_LIST.get(type), categoryItems);
                    categoryType.save();
                    LogUtil.d(TAG, "updateCategoryDb insert " + categoryType);
                } else if (categoryTypeList.size() == 1) { // 数据库中已经存在则更新数据库，且一个type只能对应一条数据
                    CategoryType updateCategoryType = categoryTypeList.get(0);
                    updateCategoryType.setCategoryItems(categoryItems);
                    updateCategoryType.save();
                    LogUtil.d(TAG, "updateCategoryDb update " + updateCategoryType);
                } else {
                    LogUtil.d(TAG, "categoryType : " + type + " size > 1, is not right");
                }

                updateQuestion(categoryItems);
            }
        }
    }

    private List<CategoryItem> updateCategoryItem(String type, String[] files) {
        List<CategoryItem> items = new ArrayList<CategoryItem>();
        for(String period : files) {
            LogUtil.d(TAG, "updateCategoryItem period = " + period);
            boolean isEmpty = LitePal.where("period == ?", period).
                    find(CategoryItem.class).isEmpty();
            LogUtil.d(TAG, "updateCategoryItem isEmpty : " + isEmpty);
            if (!isEmpty) { // 数据库中已经存在则返回，不存在就执行后面的插入数据库操作
                continue;
            }

            CategoryItem categoryItem = new CategoryItem();
            categoryItem.setPeriod(period);

            String[] periodYM = getPeroidYM(period);
            if (periodYM == null) {
                LogUtil.d(TAG, "updateCategoryItem periodYM is null");
                continue;
            }
            if (ConstantUtil.PERIOD_LIST.containsKey(periodYM[1])) {
                categoryItem.setPeriodToShow(periodYM[0] +
                        ConstantUtil.PERIOD_LIST.get(periodYM[1]));
            }
            categoryItem.setAssetsFile(type + "/" + period);
            categoryItem.setExtInfo(ConstantUtil.EXT_INFO);
            categoryItem.save();

            LogUtil.d(TAG, "updateCategoryItem categoryItem = " + categoryItem);
            items.add(categoryItem);
        }
        return items;
    }
}
